package cn.lxsir.uniapp.controller;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.intern.InternUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.lxsir.uniapp.common.Constants;
import cn.lxsir.uniapp.common.Result;
import cn.lxsir.uniapp.entity.Goods;
import cn.lxsir.uniapp.entity.Orders;
import cn.lxsir.uniapp.entity.User;
import cn.lxsir.uniapp.mapper.GoodsMapper;
import cn.lxsir.uniapp.mapper.OrdersMapper;
import cn.lxsir.uniapp.mapper.UserMapper;
import cn.lxsir.uniapp.service.IGoodsService;
import cn.lxsir.uniapp.service.IOrdersService;
import cn.lxsir.uniapp.utils.MathUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author wy
 * @since 2023-05-30
 */
@RestController
@RequestMapping("/orders")
public class OrdersController {
    @Resource
    private OrdersMapper   ordersMapper;
    @Resource
    private IOrdersService ordersService;

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private IGoodsService goodsService;
    @Resource
    private UserMapper userMapper;

    private final String now = DateUtil.now();
    @PostMapping
    public Result save(@RequestBody Orders orders){

        ordersMapper.insert(orders);
        return Result.success();
    }
    @PostMapping("/deleteBatch")
    public Result deleteBatch(@RequestBody List<Integer> ids){
        ordersMapper.deleteBatchIds(ids);
        return Result.success();
    }
    @PutMapping
    public Result update(@RequestBody Orders Order) {
        ordersMapper.updateById(Order);
        return Result.success();
    }
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Long id) {
        ordersMapper.deleteById(id);
        return Result.success();
    }
    @GetMapping("/{id}")
    public Result getById(@PathVariable Long id) {
        return Result.success(ordersMapper.selectById(id));
    }

    @PostMapping("/finish/{goodId}/{UserId}")
    public Result createOrder(@PathVariable Long goodId,@PathVariable Long UserId,@RequestParam(value = "state") Integer state) {
        Goods good = goodsMapper.selectById(goodId);
        User user = userMapper.selectById(UserId);
        String orderNo = IdUtil.getSnowflake().nextIdStr();
//        String payUrl = "http://localhost:9090/alipay/pay?subject=" + book.getName() + "&no=" + orderNo + "&total=" + book.getPrice();
        Orders order = new Orders();
        order.setName(good.getName());
        order.setNo(orderNo);
        order.setTotal(new MathUtils().getBigDecimal(good.getPrice()));
        order.setTime(now);
        order.setState(state);
        order.setUserName(user.getUsername());
        order.setUserId(user.getId());
        save(order);
        // 新建订单，扣减库存
        return Result.success();
    }
    @PostMapping("/uncertain/{goodId}/{UserId}")
    public Result createUncertainOrder(@PathVariable Long goodId,@PathVariable Long UserId,@RequestParam(value = "state") Integer state) {
        Goods good = goodsMapper.selectById(goodId);
        User user = userMapper.selectById(UserId);
        String orderNo = IdUtil.getSnowflake().nextIdStr();
//        String payUrl = "http://localhost:9090/alipay/pay?subject=" + book.getName() + "&no=" + orderNo + "&total=" + book.getPrice();
        int store=Integer.parseInt(good.getStore())-1;
        good.setStore(StrUtil.toString(store));
        goodsMapper.updateById(good);

        Orders order = new Orders();
        order.setName(good.getName());
        order.setNo(orderNo);
        order.setTotal(new MathUtils().getBigDecimal(good.getPrice()));
        order.setTime(now);
        order.setState(state);
        order.setUserName(user.getUsername());
        order.setUserId(user.getId());
        order.setGoodId(good.getId());
        save(order);
        // 新建订单，扣减库存
        return Result.success();
    }
    @GetMapping
    public IPage<Orders> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                                  @RequestParam(defaultValue = "10") Integer pageSize,
                                  @RequestParam(value = "userId",defaultValue = "0") Integer userId
    ) {
//        IPage<Orders> page = new IPage<Orders>();
        IPage<Orders> page = new Page<>(pageNum,pageSize);
//        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<Orders>();
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<Orders>();
        queryWrapper.eq(Orders::getUserId,userId);
        return  ordersService.page(page,queryWrapper);
    }

    @GetMapping("/test")
    public List<Orders> test(@RequestParam(value = "userId",defaultValue = "0") Integer userId){
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<Orders>();
        queryWrapper.eq(Orders::getUserId,userId);
        List<Orders> list = ordersService.list(queryWrapper);
        for (Orders orders : list) {
            Integer goodId = orders.getGoodId();
            orders.setGoods(goodsMapper.selectById(goodId));
        }
        return list;
    }

    @GetMapping("/money")
    public Result totalMoney(){
        String state= "已支付";
        double money = 0;
        LambdaQueryWrapper<Orders> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Orders::getState, state);
        List<Orders> orders = ordersMapper.selectList(wrapper);
        for (Orders order : orders) {
            BigDecimal total = order.getTotal();
            money += total.doubleValue();
        }
        System.out.println(money);
        return Result.success(money);
    }

    @GetMapping("/cancer")
    public Result cancer(@RequestParam(defaultValue = "0") Integer orderId){
        Orders orders = changeState(orderId, 4);
        return Result.success(ordersMapper.updateById(orders));
    }

    @Transactional
    @GetMapping("/confirm")
    public Result confirm(@RequestParam Integer orderId,@RequestParam Integer userId,@RequestParam Integer goodId){

        boolean flagPrice = false;
        boolean flagStore = false;
        MathUtils mathUtils = new MathUtils();
        //更新剩余积分
        Goods goods = goodsMapper.selectById(goodId);
        BigDecimal price = mathUtils.getBigDecimal(goods.getPrice());
        User user = userMapper.selectById(userId);
        BigDecimal integral = mathUtils.getBigDecimal(user.getIntegral());

        BigDecimal newIntegral = integral.subtract(price);

        if (integral.compareTo(new BigDecimal(0)) >= 0&&newIntegral.compareTo(new BigDecimal(0))>=0){
            flagPrice = true;
        }
        //更新库存
        int store = Integer.parseInt(goods.getStore());
        if (store>0){
            flagStore=true;
        }
        if (flagPrice&&flagStore){
            //更新状态
            Orders orders = changeState(orderId, 2);
            String now = DateUtil.now();
            orders.setPaymentTime(now);
            ordersMapper.updateById(orders);

            //更新库存
            store-=1;
            goods.setStore(StrUtil.toString(store));
            goodsMapper.updateById(goods);
            //更新积分
            user.setIntegral(StrUtil.toString(newIntegral));
            userMapper.updateById(user);
            return Result.success("确认成功");
        }else if (!flagPrice){
            return Result.error(Constants.CODE_302,"用户积分不足");
        }else if (!flagStore){
            return Result.error(Constants.CODE_301,"库存不足");
        }else {
            return Result.error(Constants.CODE_600,"系统错误");
        }
    }

    @GetMapping("/return")
    public Result returnOrder(@RequestParam Integer orderId){
        MathUtils mathUtils = new MathUtils();
        Orders orders = changeState(orderId, 4);
        Integer userId = orders.getUserId();
        Integer goodId = orders.getGoodId();
        Goods goods = goodsMapper.selectById(goodId);

        BigDecimal price = mathUtils.getBigDecimal(goods.getPrice());
        User user = userMapper.selectById(userId);
        BigDecimal integral = mathUtils.getBigDecimal(user.getIntegral());
        BigDecimal newIntegral = integral.add(price);


        user.setIntegral(StrUtil.toString(newIntegral));
        userMapper.updateById(user);


        String now = DateUtil.now();
        orders.setReturnTime(now);
        return Result.success(ordersMapper.updateById(orders));
    }


    @GetMapping("/receive")
    public Result receive(@RequestParam Integer orderId){
        Orders orders = changeState(orderId, 3);
        return Result.success(ordersMapper.updateById(orders));
    }

    private Orders changeState(Integer orderId,Integer state){
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<Orders>();
        queryWrapper.eq(Orders::getId,orderId);
        Orders orders = ordersMapper.selectOne(queryWrapper);
        orders.setState(state);
        return orders;
    }

    /**
     * 导出接口
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws Exception {
        // 从数据库查询出所有的数据
        List<Orders> list = ordersService.list();
        // 通过工具类创建writer 写出到磁盘路径
//        ExcelWriter writer = ExcelUtil.getWriter(filesUploadPath + "/用户信息.xlsx");
        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("id", "id");
        writer.addHeaderAlias("no", "订单编号");
        writer.addHeaderAlias("name", "商品名称");
        writer.addHeaderAlias("time", "购买时间");
        writer.addHeaderAlias("state", "支付状况");
        writer.addHeaderAlias("total", "总价");
        writer.addHeaderAlias("userName", "买家名");
        writer.addHeaderAlias("paymentTime", "支付时间");
        writer.addHeaderAlias("alipayNo", "支付宝流水号");
        writer.addHeaderAlias("returnTime", "退款时间");
        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(list, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("账单信息", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();

    }

    /**
     * excel 导入
     * @param file
     * @throws Exception
     */
    @PostMapping("/import")
    public Result imp(MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        // 方式1：(推荐) 通过 javabean的方式读取Excel内的对象，但是要求表头必须是英文，跟javabean的属性要对应起来
//        List<User> list = reader.readAll(User.class);

        // 方式2：忽略表头的中文，直接读取表的内容
        List<List<Object>> list = reader.read(1);
        List<Orders> order = CollUtil.newArrayList();
        for (List<Object> row : list) {
            Orders orders = new Orders();
            orders.setNo(row.get(0).toString());
            orders.setName(row.get(1).toString());
            orders.setTime(row.get(2).toString());
            orders.setState(Integer.parseInt(row.get(3).toString()));
            orders.setTotal(new MathUtils().getBigDecimal(row.get(4).toString() ));
            orders.setUserName(row.get(5).toString());
            orders.setPaymentTime(row.get(6).toString());
            orders.setAlipayNo(row.get(7).toString());
            orders.setReturnTime(row.get(8).toString());
            order.add(orders);
        }

        ordersService.saveBatch(order);
        return Result.success(true);
    }
}

